.NET问答:如何理解 IEnumerable<T> 和 IQueryable<T>
The following article is from NET技术问答 Author overflow
咨询区
stackoverflowuser:
请问类型 IQueryable<T>
和 IEnumerable<T>
有什么异同?我应该使用哪一个而不是另一个,代码如下:
IQueryable<Customer> custs = from c in db.Customers
where c.City == "<City>"
select c;
IEnumerable<Customer> custs = from c in db.Customers
where c.City == "<City>"
select c;
我知道这两者都是延迟执行,我应该如何选择?
回答区
Kasper Roma:
是的,两者都是延迟执行,我来用 SQL Server profiler
来演示两者的不同,考虑下面的代码:
MarketDevEntities db = new MarketDevEntities();
IEnumerable<WebLog> first = db.WebLogs;
var second = first.Where(c => c.DurationSeconds > 10);
var third = second.Where(c => c.WebLogID > 100);
var result = third.Where(c => c.EmailAddress.Length > 11);
Console.Write(result.First().UserName);
在 SQL Server profiler
中我捕获到了如下的sql。
"SELECT * FROM [dbo].[WebLog]"
这张表中大概有 100w 条记录,sql花费了大概 90s, 显而易见,代码首先会将 WebLog,也
就是将所有的表记录全部灌入到内存中,然后依次使用 Where()
在内存中进行过滤。接下来用 IQueryable
替代 IEnumerable
, 再次观察一下 SQL Server profiler
,可以捕获如下sql。
"SELECT TOP 1 * FROM [dbo].[WebLog] WHERE [DurationSeconds] > 10 AND [WebLogID] > 100 AND LEN([EmailAddress]) > 11"
这个 sql 大概花费了 4s。IQueryable
中有一个 Expression 属性,它存储着 表达式树
,它的完整构建在于 result 变量处(这里是延迟执行),当真正执行的时候,这个 表达式树
会被解析成 sql 到数据库中执行。
点评区
Kasper Roma
大佬说的是有理有节,图文并茂,一看就懂,大写的🐂👃,我还真的特意看了下有没有 Expression
属性 😅😅😅
//
// Summary:
// Provides functionality to evaluate queries against a specific data source wherein
// the type of the data is not specified.
public interface IQueryable : IEnumerable
{
//
// Summary:
// Gets the type of the element(s) that are returned when the expression tree associated
// with this instance of System.Linq.IQueryable is executed.
//
// Returns:
// A System.Type that represents the type of the element(s) that are returned when
// the expression tree associated with this object is executed.
Type ElementType { get; }
//
// Summary:
// Gets the expression tree that is associated with the instance of System.Linq.IQueryable.
//
// Returns:
// The System.Linq.Expressions.Expression that is associated with this instance
// of System.Linq.IQueryable.
Expression Expression { get; }
//
// Summary:
// Gets the query provider that is associated with this data source.
//
// Returns:
// The System.Linq.IQueryProvider that is associated with this data source.
IQueryProvider Provider { get; }
}
- EOF -
C#中使用 CancellationToken 处理异步任务
看完本文有收获?请转发分享给更多人
推荐关注「DotNet」,提升.Net技能
点赞和在看就是最大的支持❤️